import 'package:backend.core/core/domain/entities/user_role.dart';
import 'package:backend.core/core/domain/helpers/verify_access_token.dart';
import 'package:backend.core/core/domain/utils/either_extension.dart';
import 'package:backend.core/core/infrastructure/helpers/request_helpers.dart';
import 'package:shelf/shelf.dart';

abstract class RequireAdminAuthorization {
  Middleware call();
}

class RequireAdminAuthorizationImpl implements RequireAdminAuthorization {
  const RequireAdminAuthorizationImpl({
    required VerifyAccessToken verifyAccessToken,
  }) : _verifyAccessToken = verifyAccessToken;

  final VerifyAccessToken _verifyAccessToken;

  @override
  Middleware call() {
    return (innerHandler) {
      return (request) async {
        var accessTokenClaim = maybeExtractAccessTokenClaim(
          request: request,
        );

        if (accessTokenClaim == null) {
          final accessTokenData = extractAccessTokenData(
            request: request,
          );

          if (accessTokenData == null) {
            return Response(401);
          }

          final failureOrAccessTokenClaim = _verifyAccessToken(
            accessTokenData: accessTokenData,
          );

          if (failureOrAccessTokenClaim.isLeft()) {
            return Response(401);
          }

          accessTokenClaim = failureOrAccessTokenClaim.asRight();

          request = setAccessTokenClaim(
            request: request,
            accessTokenClaim: accessTokenClaim,
          );
        }

        if (!accessTokenClaim.userRole.isAdmin) {
          return Response(403);
        }

        final response = await Future.sync(() {
          return innerHandler(request);
        });

        return response;
      };
    };
  }
}
